use crate::error::CommonError;

//TODO: use std::collections::VecDeque;
pub struct Topic {
    name: String,
    path: String,
    content:Vec<u8> //TODO: stream-writer/reader triat
}

impl Topic {
    pub fn new(name: &str, dir: &str) -> Self{
        fn gen_path(name: &str, dir: &str) -> String{
            let mut path = String::from(dir);
            path.push_str("/");
            path.push_str(name);
            path
        }
        Self {
            name: String::from(name),
            path: gen_path(name, dir),
            content: Vec::new()
        }
    }

    pub fn append(&mut self, bytes: &[u8], start: usize, len: usize) -> Result<usize, CommonError> {
        if start >= bytes.len() {
            return Err(CommonError::IndexError);
        }
        let end = start + len;
        if start + len > bytes.len() {
            return Err(CommonError::IndexError);
        }

        if (end - start) > 0 {
            self.content.extend_from_slice(&bytes[start..end]);
        }
        Ok(end - start)
    }

    pub fn remove(&mut self, bytes: & mut [u8]) -> Result<usize, CommonError> {
        let transfer_len = if bytes.len() > self.content.len() { self.content.len() } else { bytes.len() };
        for i in 0..transfer_len {
            bytes[i] = self.content.remove(0);
        }
        Ok(transfer_len)
    }

    pub fn len(&self) -> usize {
        self.content.len()
    }
}
impl ToString for Topic {
    fn to_string(&self) -> String {
        format!("name:{},path:{},content:{:?}", self.name, self.path, self.content)
    }
}


#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_topic(){
        let mut topic = Topic::new("topic", ".");

        let bytes = "hello world".as_bytes();
        //println!("{}", &bytes[0..2]);
        let ret = topic.append(bytes, 0, bytes.len());
        assert_eq!(bytes.len(), ret.unwrap());
        //println!("{}", topic.to_string());
        
        assert!(topic.to_string().contains("name:topic"));

        let mut buf = [23; 100];
        let ret = topic.remove(&mut buf);
        assert_eq!(bytes, &buf[0..ret.unwrap()]);// read content ok
        assert_eq!(0, topic.len()); // assert topic consumed
    }
}

